import React, { FC, useMemo, useState } from "react";
import { JSONSchema, JSONSchemaLine, _, addField, flatJSONSchema } from "./utils";
export * from "./utils";
import styles from './style.less';
import JSONLine from "./JSONLine";

export interface JSONBuilderProps {
    schema: JSONSchema;
    onChange?: (schema: JSONSchema) => void;
    closeKeys?: string[];
}

const JSONBuilder: FC<JSONBuilderProps> = (props) => {
    const [ schema, updateSchema ] = useState(props.schema)
    const [ closeKeys, setCloseKeys ] = useState(new Set(props.closeKeys || []))

    const lines = useMemo(function () {
        return flatJSONSchema(schema, closeKeys)
    }, [schema, closeKeys])

    const onToggle = useMemo(function () {
        return (key: string) => {
            if (closeKeys.has(key)) {
                closeKeys.delete(key)
            } else {
                closeKeys.add(key)
            }
            setCloseKeys(new Set(closeKeys))
        }
    }, [closeKeys])

    const [onDelete, onAddChild, onUpdate] = useMemo(function () {
        const onDelete = function (keypath: string[]) {
            const result = _.set(schema, keypath, undefined, true)
            updateSchema(result)
            props.onChange?.(result)
        }
        const onAddChild = function (keypath: string[]) {
            const result = addField(schema, keypath)
            updateSchema(result)
            props.onChange?.(result)
        }
        const onUpdate = function (keypath: string[]) {
            const field = keypath[keypath.length - 1]
            const parentpath = keypath.slice(0, keypath.length - 1)
            return (line: JSONSchemaLine) => {
                let result: JSONSchema
                if (!field && parentpath.length === 0) {
                    result = line.schema
                } else if (line.field === field) {
                    result = _.set(schema, keypath, line.schema, true)
                } else {
                    result = _.replace(schema, parentpath, field, line.field, line.schema)
                    console.log(result)
                }
                updateSchema(result)
                props.onChange?.(result)
            }
        }
        return [onDelete, onAddChild, onUpdate]
    }, [schema])

    return <div className={styles.json_builder}>
        {lines.map((line, i) => {
            const { keypath } = line
            const key = keypath.join(',')
            const realpath = keypath.slice(1)
            return <JSONLine
                key={i}
                line={line}
                onToggle={() => onToggle(key)}
                onDelete={() => onDelete(realpath)}
                onAddChild={() => onAddChild([...realpath, 'properties'])}
                onAddAfter={() => onAddChild(realpath.slice(0, realpath.length - 1))}
                onUpdate={onUpdate(realpath)}
            />
        })}
    </div>
}

export default JSONBuilder